package com.hk.core.redis;

import com.hk.commons.util.AssertUtils;
import com.hk.commons.util.IDGenerator;
import com.hk.commons.util.ObjectUtils;
import com.hk.commons.util.date.DateTimeUtils;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;

/**
 * <pre>
 * Redis 每天自增生成唯一 key
 * </pre>
 *
 * @author Kevin
 * @date 2020-12-19 12:27
 */
public class RedisIncrementIdGenerator implements IDGenerator<String> {

    private final StringRedisTemplate stringRedisTemplate;

    private final String keyPrefix;

    private final String adderFormat;

    public RedisIncrementIdGenerator(String keyPrefix, StringRedisTemplate stringRedisTemplate) {
        this(keyPrefix, stringRedisTemplate, 0);
    }

    public RedisIncrementIdGenerator(String keyPrefix, StringRedisTemplate stringRedisTemplate, long startValue) {
        this(keyPrefix, stringRedisTemplate, 10, startValue);
    }

    /**
     * @param adderLength 生成Key 的位数，不足在前面用0补充
     * @param startValue  开始值，必须大于等于0
     */
    public RedisIncrementIdGenerator(String keyPrefix, StringRedisTemplate stringRedisTemplate, int adderLength,
                                     long startValue) {
        AssertUtils.isTrue(startValue >= 0, "startValue be greater than zero.");
        this.keyPrefix = keyPrefix;
        this.stringRedisTemplate = stringRedisTemplate;
        this.adderFormat = "%0" + adderLength + "d";
        var date = LocalDate.now().format(DateTimeFormatter.ofPattern(DateTimeUtils.YYYYMMDD));
        var key = keyPrefix + date;
        this.stringRedisTemplate.boundValueOps(key).set(String.valueOf(startValue), 7, TimeUnit.DAYS);// 有效期一周
    }

    /**
     * 每天都会重新记数
     *
     * @return 生成的自增数，前面会加上当前日期，格式为 {@link DateTimeUtils#YYYYMMDD}
     */
    @Override
    public String generate() {
        var date = LocalDate.now().format(DateTimeFormatter.ofPattern(DateTimeUtils.YYYYMMDD));
        var key = keyPrefix + date;
        var value = stringRedisTemplate.boundValueOps(key).increment();
        return date + String.format(adderFormat, ObjectUtils.defaultIfNull(value, 0L));
    }
}
